new function () {
    const ConfigUtil = require('./config_util');
    const LogoWindow = require('./windows/logo_window');
    const MenuWindow = require('./windows/menu_window');
    const ItemView = require('./widgets/item_view');
    const ViewUtil = require('./modules/view_util');
    const { defineValue, isHorizontalScreen } = require("./modules/utils");

    /**
     * 悬浮菜单-Rhino引擎
     * @author 大柒Se7en
     * @version 1.0.0
     * @description 此模块仅支持autojs pro 908以上Rhino引擎使用
     */
    function FloatMenu() {
        this.emitter = $events.emitter();
        this.config = new ConfigUtil(this);
        this.viewUtil = new ViewUtil(this);
        this.menuWindow = new MenuWindow(this);
        this.logoWindow = new LogoWindow(this);
        this.autoHideFloatMenuID = -1;
        init(this);
    }

    /** 状态 关闭 */
    FloatMenu.STATE_CLOSED = -1;
    /** 状态 隐藏 */
    FloatMenu.STATE_HIDE = 0;
    /** 状态 显示 */
    FloatMenu.STATE_SHOW = 1;
    /** 状态 展开 */
    FloatMenu.STATE_OPEN = 2;

    /** 菜单样式 水平 */
    FloatMenu.TYPE_MENU_HORIZONTAL = MenuWindow.TYPE_MENU_HORIZONTAL;
    /** 菜单样式 扇形 */
    FloatMenu.TYPE_MENU_CIRCULAR = MenuWindow.TYPE_MENU_CIRCULAR;

    /** 控件样式 按钮 */
    FloatMenu.STYLE_ITEM_BUTTON = ItemView.STYLE_ITEM_BUTTON;
    /** 控件样式 复选框 */
    FloatMenu.STYLE_ITEM_CHECKBOX = ItemView.STYLE_ITEM_CHECKBOX;

    FloatMenu.prototype = {

        /**
         * 悬浮球是否显示
         * @returns {boolean}
         */
        isShowing() {
            return this.getState() >= FloatMenu.STATE_SHOW;
        },

        /**
         * 悬浮球是否关闭
         * @returns {boolean}
         */
        isClosed() {
            return this.getState() === FloatMenu.STATE_CLOSED;
        },

        /**
         * 菜单是否展开
         * @returns {boolean}
         */
        isMenuOpen() {
            return this.menuWindow.isMenuOpen();
        },
        /**
         * 显示悬浮球
         */
        show() {
            this.setState(FloatMenu.STATE_SHOW);
        },

        /**
         * 隐藏悬浮球
         */
        hide() {
            this.setState(FloatMenu.STATE_HIDE);
        },

        /**
         * 关闭悬浮球
         */
        close() {
            this.setState(FloatMenu.STATE_CLOSED);
            this.closeAutoHideFLoatMenuTimer();
        },

        /**
         * 展开菜单
         */
        open() {
            this.setState(FloatMenu.STATE_OPEN);
        },
        /**
         * 设置悬浮球状态
         */
        setState(state) {
            this.state = state;
        },

        /**
         * 获取悬浮球状态
         */
        getState() {
            return this.state;
        },

        /**
         * 设置菜单样式\
         * 
         *      //设置菜单样式为扇形菜单
         *      fm.setMenuStyle(FloatMenu.TYPE_MENU_CIRCULAR);
         * @param {*} style 
         */
        setMenuStyle(style) {
            this.menuWindow.setStyle(style);
        },

        /**
         * 获取菜单样式
         */
        getMenuStyle() {
            this.menuWindow.getStyle();
        },


        /**
         * @callback ItemViewOnClickCallback
         * @param {ItemView} view
         * @returns {boolean=} 是否关闭菜单 没有返回值或者返回true保持菜单开启,返回false关闭菜单
         */

        /**
         * 注册悬浮窗事件
         * @param {string} type 悬浮窗事件 'item_click'
         * @param {ItemViewOnClickCallback} callback 'item_click'回调事件
         */
        on(type, callback) {
            return this.emitter.on(type, callback);
        },

        /**
         * 添加一个控件到菜单
         * @param {string} name 控件名称
         * @param {number=} index 可选参数 将控件添加到指定位置 默认-1 添加到最后
         */
        addItem(name, index) {
            return this.viewUtil.addItem(name, index || -1);
        },

        /**
         * 获取指定控件
         * @param {string} name 
         * @returns {ItemView|null} 控件或者null;
         */
        findView(name) {
            return this.viewUtil.findView(name);
        },

        /**
         * 获取LogoView控件
         */
        getLogoView() {
            return this.viewUtil.getLogoView();
        },

        getViewUtil() {
            return this.viewUtil;
        },
        
        getLogoWindow() {
            return this.logoWindow;
        },

        getMenuWindow() {
            return this.menuWindow;
        },

        getConfig() {
            return this.config;
        },

        resetAutoHideFloatMenuTimer() {
            if (-1 !== this.autoHideFloatMenuID) {
                clearTimeout(this.autoHideFloatMenuID);
                this.autoHideFloatMenuID = -1;
            }

            this.autoHideFloatMenuID = setTimeout(() => {
                this.setState(FloatMenu.STATE_SHOW);
            }, 3000);
        },
        closeAutoHideFLoatMenuTimer() {
            if (-1 !== this.autoHideFloatMenuID) {
                clearTimeout(this.autoHideFloatMenuID);
                this.autoHideFloatMenuID = -1;
            }
        },

        defineValue
    }


    /**
     * @param {FloatMenu} fm 
     */
    function init(fm) {
        //悬浮窗状态监听器
        fm.defineValue('state', -1, function (cunrrentstate, previousstate) {
            fm.emitter.emit('state_changed', cunrrentstate, previousstate);
        });

        var list = []
        //创建观察者 监听list数组发生改变
        Array.observe(list, changeds => {
            changeds.find(changed => {
                if (changed.type === 'splice' && changed.addedCount > 0) {
                    fm.emitter.emit('animation_end');
                    return true;
                }
                return false;
            });
        });

        fm.emitter.on('animation_end', function () {
            let actions = list.shift();
            if (actions) actions[0][actions[1]]();
        });

        fm.emitter.on('state_changed', (cunrrentstate, previousstate) => {
            if (cunrrentstate === FloatMenu.STATE_CLOSED) {
                switch (previousstate) {
                    case FloatMenu.STATE_OPEN://关闭菜单
                        list.push([fm.menuWindow, 'hide']);
                    case FloatMenu.STATE_SHOW://隐藏悬浮球
                        list.push([fm.logoWindow, 'hide']);
                    case FloatMenu.STATE_HIDE://关闭悬浮球
                        fm.logoWindow.close();
                        fm.menuWindow.close();
                }
            }
        });

        fm.on('state_changed', function (currentstate, previousstate) {
            if (currentstate === FloatMenu.STATE_OPEN) {//目标状态 展开菜单
                switch (previousstate) {
                    case FloatMenu.STATE_CLOSED:
                        fm.menuWindow.init();
                        fm.logoWindow.init();
                    case FloatMenu.STATE_HIDE:
                        list.push([fm.logoWindow, 'show']);
                    case FloatMenu.STATE_SHOW:
                        list.push([fm.menuWindow, 'open']);
                        fm.resetAutoHideFloatMenuTimer();
                        break;
                }
            }
        });

        fm.on('state_changed', (currentstate, previousstate) => {
            if (currentstate === FloatMenu.STATE_SHOW) {//目标状态 显示悬浮球
                switch (previousstate) {
                    case FloatMenu.STATE_CLOSED:
                        fm.menuWindow.init();
                        fm.logoWindow.init();
                    case FloatMenu.STATE_HIDE:
                        list.push([fm.logoWindow, 'show']);
                        break;
                    case FloatMenu.STATE_OPEN:
                        list.push([fm.menuWindow, 'hide']);
                        break;
                }
            }
        });

        fm.on('state_changed', (currentstate, previousstate) => {
            if (currentstate === FloatMenu.STATE_HIDE) {//目标状态 隐藏悬浮球
                switch (previousstate) {
                    case FloatMenu.STATE_OPEN://菜单展开
                        list.push([fm.menuWindow, 'hide']);//关闭菜单
                    case FloatMenu.STATE_SHOW://悬浮球显示
                        list.push([fm.logoWindow, 'hide']);//隐藏悬浮球
                        break;
                }
            }
        });

        //监听屏幕旋转
        setInterval(() => {
            fm.config.orientation = isHorizontalScreen();
        }, 500);
    }

    module.exports = FloatMenu;
}